#!/usr/bin/env python
# encoding: utf-8


"""
@file: sanjiaohanshu_jisuan.py
@time: 2017/1/6 下午3:15
"""
# 三角函数计算的问题
from mathsolver.functions.base import *
from sympy import sin, cos, tan, trigsimp, cot, sqrt
from mathsolver.functions.sanjiao import sanjiao_utils as su
from mathsolver.functions.sanjiao.huajian import trig_simplify


# cos35°sin95°-cos95°sin35°=()
# 直接用sympy计算出值
class SanJiaoHanShuJiSuan001(BaseFunction):
    def solver(self, *args):
        self.label.add('三角恒等变换求值')
        trig_f = args[0].sympify()
        known_eqs = su.known_trig_eqs(self.known)
        if known_eqs or len(args) > 1:
            raise Exception('Type Match Error')
        result = trigsimp(trig_f)
        if result.is_real:  # 求值
            pass
        elif su.trig_is_simped(result):  # 化简
            result = trig_simplify(result)
        else:
            raise Exception('Type Match Error')
        self.steps.append(['求得%s=%s' % (new_latex(trig_f), new_latex(result)), ''])
        self.output.append(BaseNumber(result))
        return self


# 带参数要进行化简
# 形如 trig_f1(x) = k 求 trig_f2(y) = ?
# 1 首先判断x是否大于pi/2 如果大于则化成 等价的 <pi/2 的三角函数
# 2 判断y是否大于 pi/2 如果大于则化成 等价的 < pi/2 的度数
# 3 然后根据已知的求未知的
# 记cos(-80°)=k,那么tan100°=()
class SanJiaoHanShuJiSuan002(BaseFunction):
    @staticmethod
    def _stand_trig_eq(tmp_eq):
        t_l, t_r = tmp_eq.sympify()
        t_f = t_l - t_r
        pairs = t_f.as_coefficients_dict().items()
        left_expr = sympify('0')
        other_expr = sympify('0')
        for k, v in pairs:
            if str(k).find('sin') >= 0 or str(k).find('cos') >= 0 or str(k).find('tan') >= 0 or str(k).find('cot') >= 0:
                left_expr += k * v
            else:
                other_expr += k * v
        right_expr = -other_expr
        t_coef, t_type, t_arg, _ = su.simp_trig_info(str(left_expr))
        if t_coef < 0:
            right_expr = right_expr / t_coef
            left_expr = t_type(t_arg)
        return BaseEq([left_expr, right_expr])

    @staticmethod
    def _solve_other_trig_values(trig_expr, trig_value):
        """
        已知一个三角函数值求其他三角函数值
        :param trig_expr:
        :param trig_value:
        :return:
        """
        _1, trig_type, trig_arg, _2 = su.simp_trig_info(trig_expr)
        if trig_type == sin:
            cos_value = sqrt(1 - trig_value ** 2)
            tan_value = trig_value / cos_value
            cot_value = 1 / tan_value
            return ('cos(%s)' % trig_arg, cos_value), ('tan(%s)' % trig_arg, tan_value), (
                'cot(%s)' % trig_arg, cot_value)
        elif trig_type == cos:
            sin_value = sqrt(1 - trig_value ** 2)
            tan_value = sin_value / trig_value
            cot_value = 1 / tan_value
            return ('sin(%s)' % trig_arg, sin_value), ('tan(%s)' % trig_arg, tan_value), (
                'cot(%s)' % trig_arg, cot_value)
        elif trig_type == tan:
            cos_value = sqrt(1 / (trig_value ** 2 + 1))
            sin_value = cos_value * trig_value
            cot_value = 1 / trig_value
            return ('sin(%s)' % trig_arg, sin_value), ('cos(%s)' % trig_arg, cos_value), (
                'cot(%s)' % trig_arg, cot_value)
        elif trig_type == cot:
            sin_value = sqrt(1 / (trig_value ** 2 + 1))
            cos_value = sin_value * trig_value
            tan_value = 1 / trig_value
            return ('sin(%s)' % trig_arg, cos_value), ('cos(%s)' % trig_arg, cos_value), (
                'tan(%s)' % trig_arg, tan_value)

    def solver(self, *args):
        self.label.add('三角恒等变换求值')
        known_eqs = su.known_trig_eqs(self.known).sympify()
        if len(known_eqs) > 1:
            raise Exception('Type Match Error')
        cond_eq = known_eqs[0]
        target_expr = args[0].sympify()
        cond_eq = SanJiaoHanShuJiSuan002._stand_trig_eq(BaseEq(cond_eq)).sympify()
        cond_l, cond_r = cond_eq
        cond_l1_coef, cond_l1_type, cond_l1_arg, _ = su.simp_trig_info(cond_l)
        cond_l1_arg = su.radianed(cond_l1_arg)
        cond_l2_coef, cond_l2_type, cond_l2_arg, _ = su.trig_induction(cond_l)
        cond_l2_arg = su.radianed(cond_l2_arg)
        if cond_l1_arg != cond_l1_arg:
            src_trig_print = su.print_trig_latex('%s(%s)' % (str(cond_l1_type), str(cond_l1_arg)))
            last_trig_print = su.print_trig_latex(
                '%s*%s(%s)' % (str(cond_l2_coef), str(cond_l2_type), str(cond_l2_arg)))
            self.steps.append(
                ['由题意可知 %s = %s' % (src_trig_print, last_trig_print), ''])
        new_cond_trig_type, new_cond_trig_arg = cond_l2_type, cond_l2_arg
        new_cond_r = cond_r
        if cond_l2_coef < 0:
            new_cond_r = new_cond_r / cond_l2_coef
        other_trig_values = SanJiaoHanShuJiSuan002._solve_other_trig_values(new_cond_trig_type(new_cond_trig_arg),
                                                                            new_cond_r)
        values_print = '%s=%s;%s=%s;%s=%s' % (
            su.print_trig_latex(other_trig_values[0][0]), new_latex(other_trig_values[0][1]),
            su.print_trig_latex(other_trig_values[1][0]), new_latex(other_trig_values[1][1]),
            su.print_trig_latex(other_trig_values[2][0]), new_latex(other_trig_values[2][1]))
        self.steps.append(['所以', values_print])
        target_coef, target_type, target_arg, target_const = su.trig_induction(target_expr)
        new_target_expr = sympify(target_coef) * target_type(target_arg) + target_const
        new_target_expr_sub = new_target_expr.subs(other_trig_values)
        self.steps.append(['则%s=%s' % (new_latex(target_expr), new_latex(new_target_expr)), '=' +
                           new_latex(new_target_expr_sub)])
        self.output.append(BaseSymbolValue({target_expr: new_target_expr_sub}))
        return self


class SanJiaoHanShuJiSuan(BaseFunction):
    CLS = [SanJiaoHanShuJiSuan001, SanJiaoHanShuJiSuan002]

    def solver(self, *args):
        solve_r = None
        for cl in SanJiaoHanShuJiSuan.CLS:
            try:
                solve_r = cl(verbose=True)
                solve_r.known = self.known
                solve_r = solve_r.solver(*args)
                solve_r.label.add('三角恒等变换求值')
                break
            except Exception:
                solve_r = None
        if not solve_r:
            raise 'try fail'
        return solve_r


if __name__ == '__main__':
    pass
